Title: Overeager Speed timer fix
Author: Assassin
Version: Beta 0.25
Applies to: Secret of Evermore -- US version, Spanish, French, German, and English
            European versions
Tested on: US version, and English European version (the Spanish, French, and German
           European versions are identical to it in the involved chunk)

Contents:

        NOTE: These patches are for HEADERED ROMs only!  That means a filesize of
        3146240 bytes.  Don't let any zealots convince you that headers are dangerous!

        SpdTim-U.ips = the SoE (USA) patch
        SpdTim-E.ips = the SoE (Europe - English, German, French, and Spanish) patch

        NSpdTimU.ips = the SoE (USA) anti-patch
        NSpdTimE.ips = the SoE (Europe - English, German, French, and Spanish) anti-patch

        The "Anti-patches" effectively remove this patch.

        readme.txt = this file

        speed-timer-start-orig.txt = commented original code (SoE US)
        speed-timer-start-fix.asm = commented fixed code (SoE US).  Also includes how the
                                    SoE European patch's offset and values differ from the
                                    SoE US version's.

ROM Addresses: SoE US - D1/B26A thru D1/B273
               SoE European - D1/B199 thru D1/B1A2
  (NOTE: The game actually runs the Bank Dn code in Bank 9n.)

Functions added (SoE USA and SoE European): None
Additional Square functions used (SoE USA and SoE European): None

Urgency: Medium.  The bug manifests every time you cast Speed on your character(s), so it's
         rather present.  However, its effect is quite small at low levels.  The effect
         increases as your dog levels up, gets better collars, and/or has the Omnitopia
         transform, but these circumstances are also where you can dominate much of the
         game, even with the hindrance of the bug.

============================================================================================

The latest versions of all my patches can be found at either of these sites:

http://www14.brinkster.com/assassin17/
http://home.comcast.net/~assassin17/

============================================================================================

TABLE OF CONTENTS

0. Description
1. Cause
2. For Testers
3. FAQ
4. Revision History
5. Credits
Unnumbered: Copyright notice

____________________________________________________________________________________________

0. DESCRIPTION
____________________________________________________________________________________________

The game has numerous timed statuses given by alchemy such as Defend, Atlas,
Speed, and Barrier.  Upon a status' reception, its timer starts at 1, then
counts upward each frame, until reaching a pre-determined limit and expiring.
However, Speed's timer is set to a starting value of (Dog's Defense + 1), due
to misordered code in its handler.  This means you'll get an average of a
handful fewer seconds of benefit from Speed than the intended 45.

This patch fixes things by reordering code so function calls won't overwrite a
register before it's incremented and saved.

____________________________________________________________________________________________

1. CAUSE
____________________________________________________________________________________________

It was probably just a momentary mental lapse by Square.  They got the timer
initialization/incrementation right for the other statuses I've checked.
The programmers knew what they were supposed to do, as evidenced by the code
for Atlas' and Defend's timer handlers (which I included in
speed-timer-start-orig.txt for comparison, as those statuses are very
similar to Speed, also boosting statistics).

____________________________________________________________________________________________

2. FOR TESTERS
____________________________________________________________________________________________

Any testing is appreciated.  The patch is quite simple and I tested it briefly, but it's
always possible I overlooked something.

Please provide feedback on Slick Productions:
http://slickproductions.org/

or on Mnrogar's Den:
http://mnrogar.slickproductions.org/

or PM assassin17 on the GameFAQs message boards:
http://www.gamefaqs.com/

Thanks!

____________________________________________________________________________________________

3. FAQ
____________________________________________________________________________________________

Q: In the commented disassembly, you describe both a "boost provided by status" and an
   "overall boost to X statistic" variable.  What's the point?  Can't a stat only
   be boosted by one thing at a time?

A: You're correct, to my knowledge.  However, having both a "Statistic boost provided
   by Status" and "Cumulative Boost to Statistic" does allow for more flexibility, in
   that Square could stack hypothetical boosts from different sources.  Accordingly,
   such a system means that when granting or removing a status, instead of just
   setting or zeroing the latter variable, Square sets or zeroes the former variable,
   before/after adding/subtracting it to/from the latter.  This distinction is
   relevant in another bug (which involves the subtraction of boosts when undoing
   statuses upon death), and in my upcoming fix for it.


Q: After briefly being 0, a newly-granted status' timer gets set to 1 at the same time as
   any boosts it provides are given.  With Speed's timer expiring at a frame count of
   2700, doesn't that make its duration 45 seconds minus 1 frame?

A: Yup.  Other statuses are like this, too (having an effective length of some seconds -
   1 frame).  Try not to let that bother you in-game, though.

____________________________________________________________________________________________

4. REVISION HISTORY
____________________________________________________________________________________________

Version 0.25 : July 9, 2013; August 22-23, and 25-29, 2013:

  - July 9, 2013: Posted about bug on SpeedDemosArchive.com.  Discovered it today when
    looking through the code to pin down cause of another bug with underflowing status
    boosts after death+revive.
  - August 22-23: Wrote description of bug and patch.  Verified bug is present in code of
    all 4 European versions.  Wrote .asm file for fix, including European differences.
    Wasn't complicated at all, given it just involved moving one existing instruction
    after two others.  Commented most of original code for Speed timer handler, and Atlas
    and Defend for good measure.
  - August 25-29: Made SoE USA patch and anti-patch.  Tested it.  Made European patch and
    anti-patch (which will work on all 4 versions).  Finished commenting original code.
    Tested European patch on English European ROM, hacking in Speed alchemy and Wax and
    Water with PAR codes, as I lack mid-game saves for it.  Also tested original European
    English version in-game to verify presence of bug, even though I already knew it was
    there by looking at the code.  Tweaked bug description a little, and wrote this Readme.
  - August 29, 2013: Released patch.

____________________________________________________________________________________________

5. CREDITS
____________________________________________________________________________________________

  - Denizens of SpeedDemosArchive.com (MetaSigma, TheAngryPanda, GreenAmbler, DLDarkLink)
    for discussing another bug, which involves the subtraction of statistic boosts when
    undoing statuses upon death, and possibly underflows stats.  Investigating the cause of
    that is what led me to see the Speed timer code and its flaw.

____________________________________________________________________________________________

Secret of Evermore copyright 1995 Squaresoft.
This readme and all other files in the archive (as listed above)
  copyright 2013 Assassin.
All rights reserved.
